# -*- coding: utf-8 -*-
# @Time    : 2024/7/5 16:52
# @Author  : yujiahao
# @File    : 07_fastapi_path_values_verification.py
# @description:路径参数和数值校验


from typing import Annotated
# 导入Path
from fastapi import FastAPI, Path, Query

app = FastAPI()


#  todo 1、对路径参数进行校验
@app.get("/items/{item_id}")
async def read_items(
        # 【声明元数据】可以声明与 Query 相同的所有参数。例如，要声明路径参数 item_id的 title 元数据值，你可以输入。
        # 路径参数 (Path)：用于 URL 路径的一部分，必须提供，没有默认值。
        # 查询参数 (Query)：用于 URL 中问号 ? 后面的参数，可以选择性提供，有默认值。
        item_id: Annotated[int, Path(title="我是title", description='我是描述', min_length=2)],
        q: Annotated[str | None, Query(alias="item-query")] = '我是默认值，字符串类型的',
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results


# todo 2、按需对参数排序

@app.get("/itemss/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
    """
     这里调用都是按照参数名称来赋值，所以不存在排序的问题。

     但是，如果你想不使用 Query 声明没有默认值的查询参数 q，
     同时使用 Path 声明路径参数 item_id，并使它们的顺序与上面不同，
     Python 对此有一些特殊的语法。

     通过传递 * 作为函数的第一个参数，Python 不会对该 * 做任何事情，
     但是它将知道之后的所有参数都应作为关键字参数（键值对），也被称为 kwargs，
     来调用，即使它们没有默认值。
     """

    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results


# todo 3、数值范围控制

@app.get("/item_num/{item_id}")
async def read_items_num(
        *,
        item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
        q: str,
        size: float = Query(gt=0, lt=10.5),
):
    '''
    声明数值校验：
    - gt：大于（greater than）
    - ge：大于等于（greater than or equal）
    - lt：小于（less than）
    - le：小于等于（less than or equal）

     Info:
    Query、Path 以及你后面会看到的其他类继承自一个共同的 Param 类（不需要直接使用它）。
    而且它们都共享相同的所有你已看到并用于添加额外校验和元数据的参数。

    技术细节:
    当你从 fastapi 导入 Query、Path 和其他同类对象时，它们实际上是函数。
    当被调用时，它们返回同名类的实例。

    如此，你导入 Query 这个函数。当你调用它时，它将返回一个同样命名为 Query 的类的实例。

    因为使用了这些函数（而不是直接使用类），所以你的编辑器不会标记有关其类型的错误。
    这样，你可以使用常规的编辑器和编码工具，而不必添加自定义配置来忽略这些错误。
    '''
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
